#include "components/shell.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/stat.h>

typedef enum
{
    _SCAN_TYPE_DIR,
    _SCAN_TYPE_FILE,
} scan_type_t;

static void _completion_path(sh_t *sh_hdl, int argc, const char *argv[], bool flag, scan_type_t type); // sh 专用，执行路径/文件自动补全
static void _split_path(const char **path, const char **arg_str, char buf[CONFIG_SH_MAX_LINE_LEN], const char *argv);
static void _scan_resource(sh_t *sh_hdl, const char *path, scan_type_t type, const char *arg_str);

static void _completion_path(sh_t *sh_hdl, int argc, const char *argv[], bool flag, scan_type_t type)
{
    if (argc == 0 || flag)
    {
        _scan_resource(sh_hdl, "", type, "");
    }
    else
    {
        char buf[CONFIG_SH_MAX_LINE_LEN];
        const char *path;
        const char *arg_str;

        _split_path(&path, &arg_str, buf, argv[argc - 1]);
        _scan_resource(sh_hdl, path, type, arg_str);
    }
}

static void _split_path(const char **path, const char **arg_str, char buf[CONFIG_SH_MAX_LINE_LEN], const char *argv)
{
    strcpy(buf, argv);

    char *p = strrchr(buf, '/');
    if (p == NULL)
    {
        *path = "";
        p = buf;
    }
    else
    {
        *path = buf;
        *p = '\0';
        p = &p[1];
    }
    *arg_str = p;
}

static void _scan_resource(sh_t *sh_hdl, const char *path, scan_type_t type, const char *arg_str)
{
    if (*path != '\0')
    {
        DIR *test = opendir(path);
        if (test)
            closedir(test);
        else
            return;
    }

    char buffer[CONFIG_SH_MAX_LINE_LEN] = "ls ";
    strncat(buffer, path, sizeof(buffer) - 1);
    if (type == _SCAN_TYPE_DIR)
        strncat(buffer, " -a1 -F | grep [/$]", sizeof(buffer) - 1);
    else
        strncat(buffer, " -a1 -F | grep -v [/$]", sizeof(buffer) - 1);

    FILE *fp = popen(buffer, "r");
    for (;;)
    {
        char *p = fgets(buffer, sizeof(buffer), fp);
        if (p)
        {
            char *lf = strrchr(p, '\n');
            if (lf)
            {
                lf[0] = '\0';
            }
            if (type != _SCAN_TYPE_DIR)
                p[strlen(p) - 1] = ' ';
            sh_completion_resource(sh_hdl, arg_str, p, NULL);
        }
        else
        {
            break;
        }
    }
    pclose(fp);
}

SHELL_CMD_FN(_exec_bash)
{
    if (argc)
    {
        char buf[CONFIG_SH_MAX_LINE_LEN];
        sh_merge_param(buf, sizeof(buf), argc, argv);
        int ret = system(buf);
        shell_print(sh_hdl, "\r");
        return ret;
    }
    else
    {
        shell_print(sh_hdl, "Usage: bash <command>\r\n");
        return -1;
    }
}

SHELL_CMD_CP_FN(_exec_bash_param)
{
    if (argc + flag >= 2)
    {
        _completion_path(sh_hdl, argc - 1, &argv[1], flag, _SCAN_TYPE_DIR);
        _completion_path(sh_hdl, argc - 1, &argv[1], flag, _SCAN_TYPE_FILE);
    }
}

SHELL_REGISTER_CMD(
    register_linux_shell_command,
    SHELL_SETUP_CMD("bash", "Execute bash command", _exec_bash, _exec_bash_param), //
);
